package com.jweb.framework.ws.support;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import com.jweb.framework.core.util.XMLUtils;

/**
 * 修改人： Thomas
 * 修改内容：新增 
 * 类说明：
 */
public class DelegatingStreamWriter implements XMLStreamWriter {
	
	private final ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
	private XMLStreamWriter xmlStreamWriter ;
	private QName qname ;
	private int count = 0 ;
	
	private boolean flag = false ;
	
	public DelegatingStreamWriter(){
		
		try {
			this.xmlStreamWriter = XMLUtils.createXMLWriter(this.baos , null , false);
		} catch (XMLStreamException e) {
			throw new IllegalStateException("Could not create XMLStreamWriter: " + e);
		}
		
	}
	
	
	public DelegatingStreamWriter(String str){
		try {
			this.xmlStreamWriter = XMLUtils.createXMLWriter(this.baos , str , false);
		} catch (XMLStreamException e) {
			throw new IllegalStateException("Could not create XMLStreamWriter: " + e);
		}
	}
	
	public byte[] getBytes(){
		if(!this.flag){
			return null ;
		}
		byte[] bytes = this.baos.toByteArray();//baos={<p0:queryAcctDate xmlns:p0="http://gsp.service.bankcomm.com/abstraction/atomic/technical.QueryAcctDateService/1_0" xmlns:p1="http://gsp.service.bankcomm.com/QueryAcctDateService"><p1:version>1.0</p1:version><p1:TIA><p1:TIA_CICS>AG63</p1:TIA_CICS><p1:TIA_ICS>458990</p1:TIA_ICS><p1:TIA_TRCODE>458990</p1:TIA_TRCODE><p1:TIA_TLID>EIRIBB1</p1:TIA_TLID><p1:TIA_AUTH>00</p1:TIA_AUTH><p1:TIA_TRBR>310800</p1:TIA_TRBR></p1:TIA></p0:queryAcctDate>}
		return bytes ;
	}
	
	public Source getSource(){
		return new StreamSource(new ByteArrayInputStream(getBytes()));
	}
	
	public void writeStartDocument() throws XMLStreamException {
		// writeStartDocument()编写XML声明。默认XML版本为1.0， 默认编码为UTF-8。
		this.xmlStreamWriter.writeStartDocument();
	}
	
	public void writeStartDocument(String version)  throws XMLStreamException {
		// writeStartDocument(String version)编写XML声明。默认XML版本为1.0
		this.xmlStreamWriter.writeStartDocument(version);
	}
	
	public void writeStartDocument(String str1 , String str2) throws XMLStreamException {
		try {
			if(str1 != null){
				this.xmlStreamWriter = XMLUtils.createXMLWriter(this.baos , str1 , false);
			}
		} catch (XMLStreamException e) {
			throw new IllegalStateException("Could not create XMLStreamWriter: " + e) ;
		}
	}
	
	public void writeStartElement(String localName) throws XMLStreamException {
		if(this.qname == null){
			this.qname = new QName(localName);
		}
		this.count += 1 ;
		/*
		 *  writeStartElement(String localName) 向输出写入一个开始标记。所有writeStartElement方法都在内部名称空间上
		 * 			下文中打开一个新的作用域。编写相应的EndElement导致作用域被关闭。
		 */
		this.xmlStreamWriter.writeStartElement(localName);
	}
	
	public void writeStartElement(String namespaceURI , String localName) throws XMLStreamException {
		if(this.qname == null){
			this.qname = new QName(namespaceURI , localName);
		}
		this.count += 1 ;
		// writeStartElement(String namespaceURI,String localName) 向输出写入一个开始标记。
		this.xmlStreamWriter.writeStartElement(namespaceURI , localName);
	}
	
	public void writeStartElement(String prefix , String localName , String namespaceURI) throws XMLStreamException {
		if(this.qname == null){
			this.qname = new QName(namespaceURI , localName , prefix);
		}
		this.count += 1 ;
		// writeStartElement(String prefix,String localName ,String namespaceURI):向输出写入一个开始标记。
		this.xmlStreamWriter.writeStartElement(prefix , localName , namespaceURI);
	}
	
	public void writeEndElement() throws XMLStreamException {
		this.count -= 1; 
		// writeEndElement():向依赖于writer内部状态的输出写入一个结束标记，以此确定事件的前缀和本地名称。
		this.xmlStreamWriter.writeEndElement() ;
		innerA();
	}
	
	public void innerA() throws XMLStreamException {
		if((this.count<=0) && (!this.flag)){
			// flush()：将所有缓存数据写入底层输出机制。
			this.xmlStreamWriter.flush();
			if(this.baos.size() > 0){
				this.flag = true ;
			}
		}
	}
	
	public void writeEmptyElement(String localName) throws XMLStreamException {
		if(this.qname == null){
			this.qname = new QName(localName);
		}
		// writeEmptyElement(String localName)：向输出写一个空元素标记。
		this.xmlStreamWriter.writeEmptyElement(localName);
		innerA();
	}
	
	public void writeEmptyElement(String namespaceURI , String localName) throws XMLStreamException {
		if(this.qname == null){
			this.qname = new QName(namespaceURI , localName);
		}
		// writeEmptyElement(String namespaceURI,String localName):向输出写一个空元素标记。
		this.xmlStreamWriter.writeEmptyElement(namespaceURI , localName);
		innerA();
	}
	
	public void writeEmptyElement(String prefix , String localName , String namespaceURI) throws XMLStreamException {
		if(this.qname == null){
			this.qname = new QName(namespaceURI , localName , prefix);
		}
		// writeEmptyElement(String prefix,String localName,String namespaceURI)：向输出写一个空元素标记。
		this.xmlStreamWriter.writeEmptyElement(prefix, localName, namespaceURI);
		innerA();
	}
	
	public void writeEndDocument() throws XMLStreamException {
		this.count = 0 ;
		// writeEndDocument():关闭所有开始标记并写入相应的结束标记。
		this.xmlStreamWriter.writeEndDocument();
		innerA();
	}
	
	public void close() throws XMLStreamException {
		innerA();
		this.xmlStreamWriter.close();
	}
	
	public void flush() throws XMLStreamException {
		this.xmlStreamWriter.flush();
	}
	
	public NamespaceContext getNamespaceContext(){
		// getNamespaceContext():返回当前名称空间上下文。
		return this.xmlStreamWriter.getNamespaceContext() ;
	}
	
	public String getPrefix(String uri) throws XMLStreamException {
		// getPrefix(String uri)获取绑定URI的前缀。
		return this.xmlStreamWriter.getPrefix(uri);
	}
	
	public Object getProperty(String name) throws IllegalArgumentException {
		return this.xmlStreamWriter.getProperty(name);
	}
	
	public void setDefaultNamespace(String uri) throws XMLStreamException {
		/*
		 * setDefaultNamespace(String uri):将URI绑定到默认名称空间。此URI在当前START_ELEMENT/END_ELEMENT 对的范围内绑定。如果在写入
		 * 		START_ELEMENT 之前调用此方法，则URI在根范围内绑定。
		 */
		this.xmlStreamWriter.setDefaultNamespace(uri);
	}
	
	public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
		/*
		 * setNamespaceContext(NamespaceContext context)设置前缀和URI绑定的当前名称空间上下文。此上下文成为用于写入的根名称空间上下文，并将
		 * 		替换当前的根名称空间上下文。通过将传递到此方法的上下文用作解析名称空间的根上下文，对setPrefix和setDefaultNamespace的后续调用
		 * 		将绑定名称空间。此方法只能在文档开始处调用 一次。这不会导致空间被声明。如果在名称空间上下文中存在前缀映射关系的名称空间URI，
		 *		则它将被视为已经声明，并且该前缀可以被StringWriter	使用。
		 */
		this.xmlStreamWriter.setNamespaceContext(context);
	}
	
	public void setPrefix(String prefix , String uri) throws XMLStreamException {
		/*
		 * setPrefix(String prefix,String uri)：设置绑定URI的前缀。前缀在当前START_ELEMENT/END_ELEMENT 对的范围内绑定。如果在写入
		 * 		START_ELEMENT 之前调用此方法，则前缀在根范围内绑定。
		 */
		this.xmlStreamWriter.setPrefix(prefix, uri);
	}
	
	public void writeAttribute(String localName , String value) throws XMLStreamException {
		// writeAttribute(String localName,String value)：向输出流写入一个不带前缀的属性。
		this.xmlStreamWriter.writeAttribute(localName, value);
	}
	
	public void writeAttribute(String namespaceURI , String localName , String value) throws XMLStreamException {
		// writeAttribute(String namespaceURI,String localName,String value):向输出流写入一个属性。
		this.xmlStreamWriter.writeAttribute(namespaceURI, localName, value);
	}
	
	public void writeAttribute(String prefix , String namespaceURI , String localName , String value) throws XMLStreamException {
		// writeAttribute(String prefix,String namespaceURI,String localName,String value)向输出流写入一个属性。
		this.xmlStreamWriter.writeAttribute(prefix, namespaceURI, localName, value);
	}
	
	public void writeCData(String data) throws XMLStreamException {
		// writeCData(String data)编写CData节。
		this.xmlStreamWriter.writeCData(data);
	}
	
	public void writeCharacters(char[] text , int start , int len) throws XMLStreamException {
		// writeCharacters(char[] text,int start,int len)向输出写入文本。
		this.xmlStreamWriter.writeCharacters(text, start, len);
	}
	
	public void writeCharacters(String text) throws XMLStreamException {
		// writeCharacters(String text) 向输出写入文本。
		this.xmlStreamWriter.writeCharacters(text);
	}
	
	public void writeComment(String data) throws XMLStreamException {
		// writeComment(String data)编写一个包含数据的XML注释
		this.xmlStreamWriter.writeComment(data);
	}
	
	public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
		// writeDefaultNamespace(String namespaceURI) 向流写入默认名称空间。
		this.xmlStreamWriter.writeDefaultNamespace(namespaceURI);
	}
	
	public void writeDTD(String dtd) throws XMLStreamException{
		// writeDTD(String dtd)编写DTD字节。此字符串代表XML1.0规范的整个doctypedecl产品。
		this.xmlStreamWriter.writeDTD(dtd);
	}
	
	public void writeEntityRef(String name) throws XMLStreamException {
		// writeEntityRef(String name)编写一个实体引用 。
		this.xmlStreamWriter.writeEntityRef(name);
	}
	
	public void writeNamespace(String prefix , String namespaceURI) throws XMLStreamException {
		/*
		 * writeNamespace(String prefix,String namespaceURI)向输出流写入一个名称空间。如果此方法的prefix参数为空字符串、“xmlns”或null，
		 * 		则此方法将委托给writeDefaultNamespace.
		 */
		this.xmlStreamWriter.writeNamespace(prefix, namespaceURI);
	}
	
	public void writeProcessingInstruction(String target) throws XMLStreamException {
		// writeProcessingInstruction(String target) 编写 一条处理指令
		this.xmlStreamWriter.writeProcessingInstruction(target);
	}
	
	public void writeProcessingInstruction(String target , String data) throws XMLStreamException {
		// writeProcessingInstruction(String target,String data)编写一条处理指令。
		this.xmlStreamWriter.writeProcessingInstruction(target, data);
	}

}